#pragma once
#include <AVUIFrameworkElement.h>
#include <AVUIIScrollInfo.h>

namespace AVUI {


class ScrollContentPresenter : public FrameworkElement, public IScrollInfo
{
    friend class ScrollViewer;
public:

    DECLARE_ELEMENT(ScrollContentPresenter, FrameworkElement);

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(Content);
        DECLARE_ATTRIBUTE_CONTENTPROPERTY();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<Object> get_Content() { return GetValue(get_ContentProperty()); }
    void set_Content(Object* pValue) { return SetValue(get_ContentProperty(), pValue); }

    DECLARE_DEPENDENCY_PROPERTY(CanContentScroll);
    bool get_CanContentScroll() { return AVUI::UnboxValue<bool>(GetValue(get_CanContentScrollProperty())); }
    void set_CanContentScroll(bool value) { SetValue(get_CanContentScrollProperty(), AVUI::BoxValue(value)); } 

    ScrollContentPresenter() : m_pContentCache(NULL), m_pScrollInfo(NULL), m_pScrollData(NULL) { }
    virtual ~ScrollContentPresenter();


    virtual void LineUp();
    virtual void LineDown();
    virtual void LineLeft();
    virtual void LineRight();
    virtual void PageUp();
    virtual void PageDown();
    virtual void PageLeft();
    virtual void PageRight();
    virtual Rect MakeVisible(Visual* pVisual, const Rect& rect);
    virtual void MouseWheelUp();
    virtual void MouseWheelDown();
    virtual void MouseWheelLeft();
    virtual void MouseWheelRight();

    virtual bool get_CanHorizontallyScroll();
    virtual void set_CanHorizontallyScroll(bool canHorizontallyScroll);

    virtual bool get_CanVerticallyScroll();
    virtual void set_CanVerticallyScroll(bool canVerticallyScroll);

    virtual float get_ExtentHeight();
    virtual float get_ExtentWidth();
    virtual float get_HorizontalOffset();
    virtual void set_HorizontalOffset(float horizontalOffset);
    virtual float get_VerticalOffset();
    virtual void set_VerticalOffset(float verticalOffset);

    virtual float get_ViewportWidth();
    virtual float get_ViewportHeight();

    virtual void set_ScrollOwner(ScrollViewer* pScrollViewer);
    virtual ScrollViewer* get_ScrollOwner();
    virtual Object* get_Object() { return Object::get_Object(); }

    static float ValidateInputOffset(float offset);
    static float CoerceOffset(float offset, float extent, float viewport);
    static float ComputeScrollOffsetWithMinimalScroll(float topView, float bottomView, float topChild, float bottomChild);

protected:

    virtual int get_VisualChildrenCount();
    virtual Visual* GetVisualChild(int idx);

    virtual Size MeasureOverride(const Size& constraintSize);
    virtual Size ArrangeOverride(const Size& constraintSize);

    virtual TRefCountedPtr<Geometry> GetLayoutClip(const Size& layoutSlotSize) AVUI_OVERRIDE;

private:
    static void StaticConstructor();

    bool get_IsScrollClient() { return m_pScrollInfo == this; }
    void HookupScrollingComponents();
    static void OnContentChanged(DependencyObject* pObject, DependencyPropertyChangedEventArgs* e);
    void ClearScrollData();
    void VerifyScrollData(Size viewport, Size extent);
    bool CoerceOffsets();

 

 

    class ScrollData
    {
    public:
        ScrollData() : CanHorizontallyScroll(false), CanVerticallyScroll(false), pScrollOwner(NULL) { }
        bool CanHorizontallyScroll;
        bool CanVerticallyScroll;
        Vector ComputedOffset;
        Size Extent;
        Vector Offset;
        ScrollViewer* pScrollOwner;
        Size Viewport;
    };

    ScrollData* EnsureScrollData();

    TWeakPtr<UIElement> m_pContentCache;
    IScrollInfo* m_pScrollInfo;
    ScrollData* m_pScrollData;

};


}; // namespace AVUI
